
typedef struct {
  UINT8 firmware_type;  //0:CPU   1:Memory   2:PCIe Device   3:Grub/Shim
  UINT8 firmware_detail_type;  //CPU/Memory:0     PCIe Device: 0:Raid 1:Network Card 2:NVME 3:GPU     Grub/Shim: 0:Grub 1:Shim
  UINT8 firmware_hash_len;	//use SHA256 32 bytes
  UINT8 firmware_hash_content[32];  //use SHA256 32bytes
  UINT8 firmware_version_len;  //default 1
  UINT8 firmware_version[4];  //default 1
} FIRMWARE_MEASURE_INFO;


typedef struct {
	UINT8  firmware_hash_content[32];
} MEASURE_HASH;


typedef struct {
  CHAR16            *FilePathString;
  CHAR16            *Description;
} UEFI_OS_BOOT_FILE;

UEFI_OS_BOOT_FILE  mUefiAarch64OsBootFiles[] = {
    {L"\\EFI\\deepin\\grubaa64.efi",             L"deepin"},
    {L"\\EFI\\euleros\\shimaa64.efi",            L"EulerOS"},
    {L"\\EFI\\centos\\grubaa64.efi",             L"CentOS"},
    {L"\\EFI\\debian\\grubaa64.efi",             L"Debian"},
    {L"\\EFI\\GRUB2\\GRUBAA64.EFI",              L"Hisilicon Linux"},
    {L"\\EFI\\redhat\\grubaa64.efi",             L"Redhat"},
    {L"\\EFI\\sles\\grubaa64.efi",               L"SuSE"},
    {L"\\EFI\\uos\\shimaa64.efi",                L"UOS"},
    {L"\\EFI\\uos\\grubaa64.efi",                L"UOS"},
    {L"\\EFI\\uniontech\\grubaa64.efi",          L"UOS"},
    {L"\\EFI\\ubuntu\\grubaa64.efi",             L"Ubuntu Linux"},
    {L"\\EFI\\neokylin\\shimaa64.efi",           L"Neokylin"},
    {L"\\EFI\\kylin\\shimaa64.efi",              L"Kylin"},
    {L"\\EFI\\kylin\\grubaa64.efi",              L"Kylin"},
    {L"\\EFI\\redflag\\shimaa64.efi",            L"Asianux"},
    {L"\\EFI\\ems\\shimaa64.efi",                L"EmindServer"},
    {L"\\EFI\\isoft\\shimaa64.efi",              L"iSoft"},
    {L"\\EFI\\alios\\shimaa64.efi",              L"Alibaba Linux"},
    {L"\\EFI\\alios\\grubaa64.efi",              L"Alibaba Linux"},
    {L"\\EFI\\bclinux\\shimaa64.efi",            L"BigCloud Linux"},
    {L"\\EFI\\tencent\\grubaa64.efi",            L"tencent"},
    {L"\\EFI\\tencentos\\grubaa64.efi",          L"tencentos"},
    {L"\\EFI\\opencloudos\\grubaa64.efi",        L"opencloudos"},
    {NULL,                                       NULL}
};

CHAR8 *
EFIAPI
OEMAsciiStrCpy (
  OUT     CHAR8        *Destination,
  IN      CONST CHAR8  *Source
  )
{

  CHAR8  *ReturnValue;

  //
  // Destination and source cannot overlap
  //
  ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));
  ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source));

  ReturnValue = Destination;
  while (*Source != 0) {
    *(Destination++) = *(Source++);
  }

  *Destination = 0;
  return ReturnValue;
}		

STATIC
EFI_STATUS
CollectCPUInfoAndSendHashToBMC (
    IN      LIST_ENTRY                  *List
    )
{
    EFI_STATUS                          Status;
    ASSET_INFO_WRAPPER                  *InfoWrapper;
    ASSET_CPU_COMMON_INFO               *CommonInfo;
    UINTN                               AssetIndex;
    EFI_SMBIOS_HANDLE                   SmbiosHandle;
    EFI_SMBIOS_TYPE                     SmbiosType;
    EFI_SMBIOS_PROTOCOL                 *Smbios;
    SMBIOS_TABLE_TYPE4                  *Type4Record;
    EFI_SMBIOS_TABLE_HEADER             *Record;
    CHAR8                               *OptionalStringStart;

	FIRMWARE_MEASURE_INFO  *Firmware_Info;
	UINT8 											 ResponseSize;
	UINT8 											 ResponseData[8];
	CHAR8	*FileBuffer;
	UINT64                           Size;

    Status = gBS->LocateProtocol (
                            &gEfiSmbiosProtocolGuid,
                            NULL,
                            (VOID **) &Smbios);
    if (EFI_ERROR (Status)) {
        return Status;
    }

	Firmware_Info = AllocateZeroPool (sizeof(FIRMWARE_MEASURE_INFO));
	ASSERT (Firmware_Info != NULL);
	Size = 80;
	FileBuffer = AllocateZeroPool(Size);

    AssetIndex = 0;
    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
    SmbiosType = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
    while (TRUE) {
        Status = Smbios->GetNext (Smbios, &SmbiosHandle, &SmbiosType, &Record, NULL);
        if (EFI_ERROR(Status)) {
            break;
        }

        Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
        OptionalStringStart = (CHAR8 *)(Type4Record + 1);
        //
        // The information in the record should be only valid when the CPU Socket is populated.
        //
        if ((Type4Record->Status & BIT6) != BIT6) {
            continue;
        }

        InfoWrapper = NULL;
        InfoWrapper = AllocateZeroPool (sizeof (ASSET_INFO_WRAPPER));
        CommonInfo = NULL;
        CommonInfo = AllocateZeroPool (sizeof (ASSET_CPU_COMMON_INFO));
        if (InfoWrapper == NULL || CommonInfo == NULL) {
            if (InfoWrapper != NULL) {
                FreePool (InfoWrapper);
            }
            if (CommonInfo != NULL) {
                FreePool (CommonInfo);
            }
            return EFI_OUT_OF_RESOURCES;
        }
        InfoWrapper->Signature = CPU_ASSET_COMMON_INFO_WRAPPER_SIGNATURE;
        InfoWrapper->AssetDeviceType = AssetDeviceTypeCpu;
        InfoWrapper->AssetInfoType = AssetInfoTypeCommon;
        InfoWrapper->AssetIndex = AssetIndex;
        if (Type4Record->Status == 0x41) { // Populated & Enabled
            InfoWrapper->Enabled = TRUE;
        }
        InfoWrapper->InfoPtr = CommonInfo;
        InfoWrapper->InfoSize = sizeof (*CommonInfo);
        CommonInfo->Sku = (UINT8)GetSku (AssetIndex);
        AsciiSPrint (CommonInfo->ProcessorName,
                            sizeof (CommonInfo->ProcessorName),
                            "%a",
                            GetSmbiosStringByIndex (OptionalStringStart, Type4Record->ProcessorVersion));
        CommonInfo->ProcessorId = *(UINT64*)&Type4Record->ProcessorId;      
  
        CommonInfo->CurrentSpeed = Type4Record->CurrentSpeed;
        CommonInfo->Core = ((Type4Record->CoreCount == 0xFF) ? Type4Record->CoreCount2 : (UINT16)Type4Record->CoreCount);
        CommonInfo->ThreadCount = ((Type4Record->ThreadCount == 0xFF) ? Type4Record->ThreadCount2 : (UINT16)Type4Record->ThreadCount);
        CommonInfo->UsedCore = ((Type4Record->EnabledCoreCount == 0xFF) ? Type4Record->EnabledCoreCount2 : (UINT16)Type4Record->EnabledCoreCount);
        CommonInfo->L1Cache = ((UINT16)(GetCacheSize(Type4Record->L1CacheHandle-1) / CommonInfo->Core)) + ((UINT16)(GetCacheSize(Type4Record->L1CacheHandle) / CommonInfo->Core));    
        CommonInfo->L2Cache = (UINT16)(GetCacheSize(Type4Record->L2CacheHandle) / CommonInfo->Core);    
        CommonInfo->L3Cache = 32*1024;	
				CommonInfo->CpuTdp = 400;
        CommonInfo->Characteristics = Type4Record->ProcessorCharacteristics;
        CommonInfo->PPIN  = GetCpuPpinValue(AssetIndex);
        CommonInfo->ProcessorType = Type4Record->ProcessorType;
        CommonInfo->ProcessorArchitecture =SysInvProcessorArchitectureARM ; 
        CommonInfo->InstructionSet = SysInvInstructionSetARM_A64;
        AsciiSPrint  (CommonInfo->SerialNumber,
                          sizeof (CommonInfo->SerialNumber),
                          "%a",
                          GetSmbiosStringByIndex (OptionalStringStart, Type4Record->SerialNumber));

		OEMAsciiStrCpy (FileBuffer + AsciiStrLen (FileBuffer), CommonInfo->SerialNumber);
		DEBUG ((DEBUG_INFO, "FileBuffer: %a\n",   FileBuffer));	
		DEBUG ((DEBUG_INFO, "FileBuffer Len: %x\n", AsciiStrLen(FileBuffer)));

        InsertTailList (List, &InfoWrapper->Link);

        AssetIndex++;
    }
	

	Sha256Hash(FileBuffer, AsciiStrLen(FileBuffer), Firmware_Info->firmware_hash_content, 32);
	DEBUG ((DEBUG_INFO, "SHA256 Hash\n"));
	for (INTN j = 0; j < 32; j++) {
		DEBUG ((DEBUG_INFO, "%x ",Firmware_Info->firmware_hash_content[j]));
	}
	DEBUG ((DEBUG_INFO, "\n"));

	FreePool(FileBuffer);

	Firmware_Info->firmware_type = 0;
	Firmware_Info->firmware_detail_type = 0;		
	Firmware_Info->firmware_version_len = 4;
	Firmware_Info->firmware_version[0] = 1;
	Firmware_Info->firmware_hash_len = 32;
	
	ResponseSize = sizeof (ResponseData);
	Status = EfiSendCommandToBMC (
						 0x3C,
						 0xF3,
						 (UINT8 *)Firmware_Info,
						 sizeof (FIRMWARE_MEASURE_INFO),
						 ResponseData,
						 &ResponseSize
						 );
	DEBUG ((DEBUG_INFO, "EfiSendCommandToBMC return %r\n", Status));
	DEBUG ((DEBUG_INFO, "ResponseData = %x\n", ResponseData));

    return EFI_SUCCESS;
}


STATIC
EFI_STATUS
CollectMemoryInfoAndSendHashToBMC (
    IN      LIST_ENTRY                *List
    )
{
    EFI_STATUS                        Status;
    ASSET_INFO_WRAPPER                *InfoWrapper;
    ASSET_MEMORY_COMMON_INFO          *CommonInfo;
    ASSET_MEMORY_PRIVATE_INFO         *PrivateInfo;
    UINTN                             AssetIndex;
    EFI_SMBIOS_HANDLE                 SmbiosHandle;
    EFI_SMBIOS_TYPE                   SmbiosType;
    EFI_SMBIOS_PROTOCOL               *Smbios;
    SMBIOS_TABLE_TYPE17               *Type17Record;
    EFI_SMBIOS_TABLE_HEADER           *Record;
    UINT8                             SocketIndex;
    UINT8                             ChannelIndex;
    UINT8                             DimmIndex;
    CHAR8                             *OptionalStringStart;
    UINT16                            DimmSize;
    BOOLEAN                           Enabled;
		UINT8               			  Count;

	FIRMWARE_MEASURE_INFO  *Firmware_Info;
	UINT8 											 ResponseSize;
	UINT8 											 ResponseData[8];
	CHAR8	*FileBuffer;
	UINT64                           Size;

    Status = gBS->LocateProtocol (
                          &gEfiSmbiosProtocolGuid,
                          NULL,
                          (VOID **) &Smbios);
    if (EFI_ERROR (Status)) {
        return Status;
    }

	Firmware_Info = AllocateZeroPool (sizeof(FIRMWARE_MEASURE_INFO));
	ASSERT (Firmware_Info != NULL);
	Size = 320;
	FileBuffer = AllocateZeroPool(Size);


    AssetIndex = 0;
    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
    SmbiosType = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
    while (TRUE) {
        Status = Smbios->GetNext (Smbios, &SmbiosHandle, &SmbiosType, &Record, NULL);
        if (EFI_ERROR(Status)) {
            DEBUG((DEBUG_INFO, "%a() L%d: %r\n", __FUNCTION__, __LINE__, Status));
            break;
        }

        Type17Record = (SMBIOS_TABLE_TYPE17 *) Record;
        if (Type17Record->Speed == 0) {
            DEBUG((DEBUG_INFO, "%a() L%d: %r\n", __FUNCTION__, __LINE__, Status));
            continue;
        }
		
        OptionalStringStart = (CHAR8 *) ((UINT8 *) Type17Record + Type17Record->Hdr.Length);
        Status = DeviceLocatorToSocketChannelDimmIndex (GetSmbiosStringByIndex (OptionalStringStart, Type17Record->DeviceLocator), &SocketIndex, &ChannelIndex, &DimmIndex);
        if (EFI_ERROR(Status)) {
            DEBUG((DEBUG_ERROR, "%a() L%d: %r\n", __FUNCTION__, __LINE__, Status));
            //continue;
        }
        AssetIndex = SocketIndex * MAX_DIMM_SOCKET + ChannelIndex * MAX_DIMM + DimmIndex;
				Count = ChannelIndex * MAX_DIMM + DimmIndex;	
        //
        // The information in the record should be only valid when the CPU Socket is populated.
        //
        InfoWrapper = NULL;
        InfoWrapper = AllocateZeroPool (sizeof (ASSET_INFO_WRAPPER));
        CommonInfo = NULL;
        CommonInfo = AllocateZeroPool (sizeof (ASSET_MEMORY_COMMON_INFO));
        if (CommonInfo == NULL || InfoWrapper == NULL) {
            if (CommonInfo != NULL) {
                FreePool (CommonInfo);
            }
            if (InfoWrapper != NULL) {
                FreePool (InfoWrapper);
            }
            return EFI_OUT_OF_RESOURCES;
        }

        InfoWrapper->Signature = MEMORY_ASSET_COMMON_INFO_WRAPPER_SIGNATURE;
        InfoWrapper->AssetDeviceType = AssetDeviceTypeMem;
        InfoWrapper->AssetInfoType = AssetInfoTypeCommon;
        InfoWrapper->AssetIndex = AssetIndex;
        InfoWrapper->InfoPtr = CommonInfo;
        InfoWrapper->InfoSize = sizeof (*CommonInfo);
        Enabled = IsDimmEnabled (SocketIndex, ChannelIndex, DimmIndex);
        InfoWrapper->Enabled = Enabled;
        AsciiSPrint  (CommonInfo->Manufacture,
                          sizeof (CommonInfo->Manufacture),
                          "%a",
                          GetSmbiosStringByIndex (OptionalStringStart, Type17Record->Manufacturer));
        CommonInfo->MaxSpeed = Type17Record->Speed;
        CommonInfo->CurrentSpeed = Type17Record->ConfiguredMemoryClockSpeed;
        CommonInfo->MemoryType = Type17Record->MemoryType;
        CommonInfo->TypeDetail = *(UINT16*)&Type17Record->TypeDetail;
        CommonInfo->Rank = Type17Record->Attributes & 0xF;
        CommonInfo->ConfiguredVoltage = Type17Record->ConfiguredVoltage;
        DimmSize = 0;
        if (Type17Record->Size == 0xFFFF) {
            DimmSize = 0xFFFF; // According to SMBIOS, 0xFFFF indicates UNKNOWN.
        } else if (Type17Record->Size == 0x7FFF) {
            DimmSize = (UINT16)((Type17Record->ExtendedSize & 0x7FFFFFFF) >> 10); // MB -> GB
        } else {
            if (Type17Record->Size & BIT15) {
                DimmSize = 1; // Smaller than 1GB
            } else {
                DimmSize = Type17Record->Size >> 10; // MB -> GB
            }
        }
        CommonInfo->PhysicalSize = DimmSize;

				if(Type17Record->DataWidth > 0xff){
					CommonInfo->DataWidth = (UINT8)(Type17Record->DataWidth & 0xFF);
				}else {
					CommonInfo->DataWidth = (UINT8)(Type17Record->DataWidth);
				}

        InsertTailList (List, &InfoWrapper->Link);

        InfoWrapper = NULL;
        InfoWrapper = AllocateZeroPool (sizeof (ASSET_INFO_WRAPPER));
        PrivateInfo = NULL;
        PrivateInfo = AllocateZeroPool (sizeof (ASSET_MEMORY_PRIVATE_INFO));
        if (PrivateInfo == NULL || InfoWrapper == NULL) {
            if (PrivateInfo != NULL) {
                FreePool (PrivateInfo);
            }
            if (InfoWrapper != NULL) {
                FreePool (InfoWrapper);
            }
            return EFI_OUT_OF_RESOURCES;
        }

        InfoWrapper->Signature = MEMORY_ASSET_PRIVATE_INFO_WRAPPER_SIGNATURE;
        InfoWrapper->AssetDeviceType = AssetDeviceTypeMem;
        InfoWrapper->AssetInfoType = AssetInfoTypePrivate;
        InfoWrapper->AssetIndex = AssetIndex;
        InfoWrapper->Enabled = Enabled;
        InfoWrapper->InfoPtr = PrivateInfo;
        InfoWrapper->InfoSize = sizeof (*PrivateInfo);
				
				//Status = GetSmbiosType17SNStr(Dimm->spd_data, PrivateInfo->SerialNumber);
        AsciiSPrint  (PrivateInfo->SerialNumber,
                          sizeof (PrivateInfo->SerialNumber),
                          "%a",
                          GetSmbiosStringByIndex (OptionalStringStart, Type17Record->SerialNumber));
        AsciiSPrint  (PrivateInfo->PartNumber,
                          sizeof (PrivateInfo->PartNumber),
                          "%a",
                          GetSmbiosStringByIndex (OptionalStringStart, Type17Record->PartNumber));
        AsciiSPrint  (PrivateInfo->AssetTag,
                          sizeof (PrivateInfo->AssetTag),
                          "%a",
                          GetSmbiosStringByIndex (OptionalStringStart, Type17Record->AssetTag));									
		
		OEMAsciiStrCpy (FileBuffer + AsciiStrLen (FileBuffer), PrivateInfo->SerialNumber);
		DEBUG ((DEBUG_INFO, "FileBuffer: %a\n",   FileBuffer)); 
		DEBUG ((DEBUG_INFO, "FileBuffer Len: %x\n", AsciiStrLen(FileBuffer)));				
        InsertTailList (List, &InfoWrapper->Link);
    }

	Sha256Hash(FileBuffer, AsciiStrLen(FileBuffer), Firmware_Info->firmware_hash_content, 32);
	DEBUG ((DEBUG_INFO, "SHA256 Hash\n"));
	for (INTN j = 0; j < 32; j++) {
		DEBUG ((DEBUG_INFO, "%x ",Firmware_Info->firmware_hash_content[j]));
	}
	DEBUG ((DEBUG_INFO, "\n"));

	FreePool(FileBuffer);

	Firmware_Info->firmware_type = 1;
	Firmware_Info->firmware_detail_type = 0;		
	Firmware_Info->firmware_version_len = 4;
	Firmware_Info->firmware_version[0] = 1;
	Firmware_Info->firmware_hash_len = 32;
	
	ResponseSize = sizeof (ResponseData);
	Status = EfiSendCommandToBMC (
						 0x3C,
						 0xF3,
						 (UINT8 *)Firmware_Info,
						 sizeof (FIRMWARE_MEASURE_INFO),
						 ResponseData,
						 &ResponseSize
						 );
	DEBUG ((DEBUG_INFO, "EfiSendCommandToBMC return %r\n", Status));
	DEBUG ((DEBUG_INFO, "ResponseData = %x\n", ResponseData));

    return EFI_SUCCESS;
}

STATIC
EFI_STATUS
CollectPCIeInfoAndSendHashToBMC (
    IN      LIST_ENTRY                *List
    )
{
    EFI_STATUS                        Status;
    ASSET_INFO_WRAPPER                *InfoWrapper;
    ASSET_PCIE_COMMON_INFO            *CommonInfo;
    ASSET_PCIE_NETWORK_INFO           *NetworkInfo;
    EFI_PCI_IO_PROTOCOL               *PciIo;
    PCI_TYPE01                        PciConfigHeader;
    UINTN                             HandleCount;
    EFI_HANDLE                        *HandleBuffer = NULL;
    UINTN                             Index;
    UINTN                             PciSegment;
    UINTN                             PciBus;
    UINTN                             PciDevice;
    UINTN                             PciFunction;


	FIRMWARE_MEASURE_INFO  *Firmware_Info;
	UINT8 											 ResponseSize;
	UINT8 											 ResponseData[8];
	CHAR8	*FileBuffer;
	UINT64                           Size;
	
	Firmware_Info = AllocateZeroPool (sizeof(FIRMWARE_MEASURE_INFO));
	ASSERT (Firmware_Info != NULL);
	Size = 320;
	FileBuffer = AllocateZeroPool(Size);

    FindAllRootBridgeAndDownStreamPort (&RootBridgeList);

    Status = gBS->LocateHandleBuffer (
                                ByProtocol,
                                &gEfiPciIoProtocolGuid,
                                NULL,
                                &HandleCount,
                                &HandleBuffer);
    if (EFI_ERROR(Status) || NULL == HandleBuffer) {    
        return Status;
    }
    DeviceIndex = 0;
    for (Index = 0; Index < HandleCount; Index++) {
        Status = gBS->HandleProtocol (
                                  HandleBuffer[Index],
                                  &gEfiPciIoProtocolGuid,
                                  (VOID **) &PciIo);
        if (EFI_ERROR (Status)) {
            continue;
        }
        if (!IsPciExist(PciIo)) {
            continue;
        }

        Status = PciIo->GetLocation (
                                PciIo,
                                &PciSegment,
                                &PciBus,
                                &PciDevice,
                                &PciFunction);
        if (EFI_ERROR (Status)) {
            continue;
        }
        Status = PciIo->Pci.Read (
                                PciIo,
                                EfiPciIoWidthUint32,
                                0,
                                sizeof (PciConfigHeader) / sizeof (UINT32),
                                &PciConfigHeader);
        Status = PciIo->Pci.Read (
                                PciIo,
                                EfiPciIoWidthUint32,
                                0,
                                sizeof (PciType00) / sizeof (UINT32),
                                &PciType00);
        if (EFI_ERROR (Status)) {
            continue;
        }
        if (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
            continue;
        }
	    if (PciType00.Hdr.ClassCode[2] == PCI_CLASS_SYSTEM_PERIPHERAL) {
	        DEBUG ((DEBUG_INFO, " Pcie: the HandleCount is a system peripheral\n"));
                 continue;
            }
		
		if ((PciConfigHeader.Hdr.VendorId == 0x1912) && ((PciConfigHeader.Hdr.DeviceId == 0x0014))){
			DEBUG ((DEBUG_INFO, "Grubby Test: Pcie: skip [PCIE to USB controller\n"));
			continue;
        }

		if ((PciConfigHeader.Hdr.VendorId == 0x1A03) && ((PciConfigHeader.Hdr.DeviceId == 0x2000))){
			DEBUG ((DEBUG_INFO, "Grubby Test: Pcie: skip [ASPEED controller\n"));														
			continue;
			}
			if ((PciConfigHeader.Hdr.VendorId == 0x1A03) && ((PciConfigHeader.Hdr.DeviceId == 0x2402))){
				DEBUG ((DEBUG_INFO, "Grubby Test: Pcie: skip [ASPEED H2B controller\n"));														
				continue;
				}
        RootBridge = GetRootBridgeBelongTo (&RootBridgeList, (UINT16)PciSegment, (UINT8)PciBus);
        if (RootBridge == NULL) {
            continue;
        }
        RootBridge->ReferenceCount++;

        InfoWrapper = NULL;
        InfoWrapper = AllocateZeroPool (sizeof (ASSET_INFO_WRAPPER));
        if (InfoWrapper == NULL) {
            if(HandleBuffer) gBS->FreePool(HandleBuffer);
            return EFI_OUT_OF_RESOURCES;
        }

        if (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
            BufferSize = 6;
            TotalBufferSize = 6;
         ZeroMem (Buffer, MacAddressBufferLength);


            if (!EFI_ERROR(Status)) {
                NetworkInfo = AllocateZeroPool (sizeof (ASSET_PCIE_NETWORK_INFO) + BufferSize);
                if (NetworkInfo == NULL) {
                    FreePool (InfoWrapper);
                    if(HandleBuffer) {
                        gBS->FreePool(HandleBuffer);
                    }
                    return EFI_OUT_OF_RESOURCES;
                }

                NetworkInfo->MacNum = (UINT8)(TotalBufferSize/6);

                CopyMem (&NetworkInfo->MacAddress[0], Buffer, TotalBufferSize);
                InfoWrapper->InfoSize = sizeof (ASSET_PCIE_NETWORK_INFO) + TotalBufferSize;
				
				OEMAsciiStrCpy (FileBuffer + AsciiStrLen (FileBuffer), (CHAR8  *)Buffer);
				DEBUG ((DEBUG_INFO, "FileBuffer Len: %x\n", AsciiStrLen(FileBuffer)));
				for (INTN j = 0; j < AsciiStrLen(FileBuffer); j++) {
					DEBUG ((DEBUG_INFO, "%x ",FileBuffer[j]));
				}
				DEBUG ((DEBUG_INFO, "\n"));

            }
            else {
                NetworkInfo = AllocateZeroPool (sizeof (ASSET_PCIE_NETWORK_INFO));
                if (NetworkInfo == NULL) {
                    FreePool (InfoWrapper);
                    if(HandleBuffer) {
                        gBS->FreePool(HandleBuffer);
                    }
                    return EFI_OUT_OF_RESOURCES;
                }
                NetworkInfo->MacNum = 0;
                InfoWrapper->InfoSize = sizeof (ASSET_PCIE_NETWORK_INFO);
            }
            CHAR8                       *PnBuffer = NULL;
            CHAR8                       *SnBuffer = NULL;

            PnBuffer = AllocateZeroPool (PCIE_NIC_PNSN_BUFFER_LENGTH);
            SnBuffer = AllocateZeroPool (PCIE_NIC_PNSN_BUFFER_LENGTH);
            if (NULL != PnBuffer && NULL != SnBuffer) {
                Status = OemReadVpdPnSnByHandle (HandleBuffer[Index], PnBuffer, SnBuffer);
                if (!EFI_ERROR(Status)) {
                    AsciiSPrint (&NetworkInfo->PartNumber[0], PCIE_NIC_PNSN_BUFFER_LENGTH, &PnBuffer[1]);
                    AsciiSPrint (&NetworkInfo->SerialNumber[0], PCIE_NIC_PNSN_BUFFER_LENGTH, &SnBuffer[1]);
                }
            }
            if (NULL != PnBuffer) {
                FreePool (PnBuffer);
                PnBuffer = NULL;
            }
            if (NULL != SnBuffer) {
                FreePool (SnBuffer);
                SnBuffer = NULL;
            }
            InfoWrapper->Signature = PCIE_ASSET_NETWORK_INFO_WRAPPER_SIGNATURE;
            InfoWrapper->InfoPtr = NetworkInfo;
        } else {
            CommonInfo = AllocateZeroPool (sizeof (ASSET_PCIE_COMMON_INFO));
            if (CommonInfo == NULL) {
                FreePool (InfoWrapper);
                if(HandleBuffer) {
                    gBS->FreePool(HandleBuffer);
                }
                return EFI_OUT_OF_RESOURCES;
            }
            InfoWrapper->Signature = PCIE_ASSET_COMMON_INFO_WRAPPER_SIGNATURE;
            InfoWrapper->InfoPtr = CommonInfo;
            InfoWrapper->InfoSize = sizeof (ASSET_PCIE_COMMON_INFO);
        }

        InfoWrapper->AssetDeviceType = AssetDeviceTypePcie;
        InfoWrapper->AssetInfoType = AssetInfoTypeCommon;
        InfoWrapper->AssetIndex = DeviceIndex;
        InfoWrapper->Enabled = TRUE;
        DeviceIndex++;
        //
        // Common Information
        //
        CommonInfo = (ASSET_PCIE_COMMON_INFO*)InfoWrapper->InfoPtr;
        CommonInfo->VendorId = PciConfigHeader.Hdr.VendorId;
        CommonInfo->DeviceId = PciConfigHeader.Hdr.DeviceId;
        CommonInfo->SVID = PciType00.Device.SubsystemVendorID;
        CommonInfo->SSID = PciType00.Device.SubsystemID;
        CommonInfo->SegmentNumber = (UINT16)PciSegment;
        CommonInfo->BusNumber = (UINT8)PciBus;
        CommonInfo->DeviceNumber = (UINT8)PciDevice;
        CommonInfo->FunctionNumber = (UINT8)PciFunction;
        CommonInfo->RootBus = (UINT8)RootBridge->PciBus;
        CommonInfo->RootDev = (UINT8)RootBridge->PciDevice;
        CommonInfo->RootFun = (UINT8)RootBridge->PciFunction;
        if (Bridge[0] != NULL) {
            CommonInfo->LastRootBus = (UINT8)Bridge[0]->PciBus;
            CommonInfo->LastRootDev = (UINT8)Bridge[0]->PciDevice;
            CommonInfo->LastRootFun = (UINT8)Bridge[0]->PciFunction;
        }
        if (Bridge[3] != NULL) {
            CommonInfo->SecondRootBus = (UINT8)Bridge[3]->PciBus;
            CommonInfo->SecondRootDev = (UINT8)Bridge[3]->PciDevice;
            CommonInfo->SecondRootFun = (UINT8)Bridge[3]->PciFunction;
        }
        if (Bridge[2] != NULL) {
            CommonInfo->ThirdRootBus = (UINT8)Bridge[2]->PciBus;
            CommonInfo->ThirdRootDev = (UINT8)Bridge[2]->PciDevice;
            CommonInfo->ThirdRootFun = (UINT8)Bridge[2]->PciFunction;
        }
        if (Bridge[1] != NULL) {
            CommonInfo->FourthRootBus = (UINT8)Bridge[1]->PciBus;
            CommonInfo->FourthRootDev = (UINT8)Bridge[1]->PciDevice;
            CommonInfo->FourthRootFun = (UINT8)Bridge[1]->PciFunction;
        }

        CommonInfo->ClassCode = PciConfigHeader.Hdr.ClassCode[2];
        CommonInfo->SubClassCode = PciConfigHeader.Hdr.ClassCode[1];
        CommonInfo->Interface = PciConfigHeader.Hdr.ClassCode[0];
        CommonInfo->PcieSlot = (UINT8)RootBridge->SlotNumber;
        	   
        InsertTailList (List, &InfoWrapper->Link);
    }

	Sha256Hash(FileBuffer, AsciiStrLen(FileBuffer), Firmware_Info->firmware_hash_content, 32);
	DEBUG ((DEBUG_INFO, "SHA256 Hash\n"));
	for (INTN j = 0; j < 32; j++) {
		DEBUG ((DEBUG_INFO, "%x ",Firmware_Info->firmware_hash_content[j]));
	}
	DEBUG ((DEBUG_INFO, "\n"));

	FreePool(FileBuffer);

	Firmware_Info->firmware_type = 2;
	Firmware_Info->firmware_detail_type = 1;		
	Firmware_Info->firmware_version_len = 4;
	Firmware_Info->firmware_version[0] = 1;
	Firmware_Info->firmware_hash_len = 32;
	
	ResponseSize = sizeof (ResponseData);
	Status = EfiSendCommandToBMC (
						 0x3C,
						 0xF3,
						 (UINT8 *)Firmware_Info,
						 sizeof (FIRMWARE_MEASURE_INFO),
						 ResponseData,
						 &ResponseSize
						 );
	DEBUG ((DEBUG_INFO, "EfiSendCommandToBMC return %r\n", Status));
	DEBUG ((DEBUG_INFO, "ResponseData = %x\n", ResponseData));


    ClearUnreferencedRootBridge (&RootBridgeList);
    DumpRootBridge (&RootBridgeList);

    CleanUpRootBridgeList (&RootBridgeList);
    if(HandleBuffer) {
        gBS->FreePool(HandleBuffer);
    }
    if (0 == DeviceIndex) {
        DEBUG((DEBUG_ERROR, "%a() L%d: Error: No PCIE device discovered.\n", __FUNCTION__, __LINE__));
        return EFI_NOT_FOUND;
    }
    return EFI_SUCCESS;
}

/**
  Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
  mesure grbu/shim HASH and sent to BMC.

  @param[in]  Event   The Event that is being processed.
  @param[in]  Context The Event Context.

**/
VOID
EFIAPI
MeasureOSBootFileOnReadyToBoot (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  EFI_BOOT_MANAGER_LOAD_OPTION    *LoadOptions;
  UINTN                           LoadOptionCount;
  EFI_STATUS                      Status;
  CHAR16                          *DevicePathStr;
	UINTN                           Index;
	UINTN                           i;
	CHAR16                          *String;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;
  EFI_FILE_HANDLE                  Root;
  EFI_FILE_HANDLE                  ThisFile;
  UINTN                            BufferSize;
  UINT64                           Size;
  EFI_FILE_INFO                    *Info;
	EFI_PHYSICAL_ADDRESS	*FileBuffer;
  FIRMWARE_MEASURE_INFO  *Firmware_Info;
  UINT8                        ResponseSize;
  UINT8                        ResponseData[8];
	EFI_HANDLE                DevHandle;

  Root     = NULL;
  ThisFile = NULL;

	LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeBoot);
	for (Index = 0; Index < LoadOptionCount; Index++) {
		DEBUG ((
			DEBUG_INFO,
			" 	 %s%04x: %s \t\t 0x%04x\n",
			mBdsLoadOptionName[LoadOptionTypeBoot],
			LoadOptions[Index].OptionNumber,
			LoadOptions[Index].Description,
			LoadOptions[Index].Attributes
			));
		DevicePathStr = ConvertDevicePathToText (LoadOptions[Index].FilePath, FALSE, FALSE);
		DEBUG ((DEBUG_INFO, "DevicePath: %s\n", DevicePathStr));

		Firmware_Info = AllocateZeroPool (sizeof(FIRMWARE_MEASURE_INFO));
		ASSERT (Firmware_Info != NULL);

		for (i = 0; mUefiOsBootFiles[i].FilePathString != NULL; i++) {
			String = StrStr(DevicePathStr, mUefiOsBootFiles[i].FilePathString);
			if(String != NULL){
				DEBUG ((DEBUG_INFO, "String: %s\n", String));
				if(StrStr(mUefiOsBootFiles[i].FilePathString, L"shim") != NULL)
				{
					Firmware_Info->firmware_type = 3;
					Firmware_Info->firmware_detail_type = 0;
				}
				else if(StrStr(mUefiOsBootFiles[i].FilePathString, L"grub") != NULL)
				{
					Firmware_Info->firmware_type = 3;
					Firmware_Info->firmware_detail_type = 0;
				} 				
				else
				{
					Firmware_Info->firmware_type = 3;
					Firmware_Info->firmware_detail_type = 0;
				}
				//
				// Handle the file system interface to the device
				//
				Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &LoadOptions[Index].FilePath, &DevHandle);
				if (EFI_ERROR (Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				gBS->HandleProtocol (DevHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Volume);
				if (EFI_ERROR (Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				Status = Volume->OpenVolume (
													 Volume,
													 &Root
													 );
				if (EFI_ERROR (Status)) {
					Root = NULL;
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				Status = Root->Open (Root, &ThisFile, mUefiOsBootFiles[i].FilePathString, EFI_FILE_MODE_READ, 0);
				if (EFI_ERROR (Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				//
				// Get file size
				//
				BufferSize	= SIZE_OF_EFI_FILE_INFO + 200;
				Info	 = NULL;
				Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);
				if (EFI_ERROR (Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				Status = ThisFile->GetInfo (
														 ThisFile,
														 &gEfiFileInfoGuid,
														 &BufferSize,
														 Info
														 );
				if (EFI_ERROR (Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				Size = Info->FileSize;
				DEBUG ((DEBUG_INFO, "Info->FileSize = %x\n",Info->FileSize));

				FileBuffer = AllocatePool(Size);
				if (EFI_ERROR(Status)) {
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}
				Status = ThisFile->Read (ThisFile, &Size, FileBuffer);
				if (EFI_ERROR(Status)) {
					FreePool(FileBuffer);
					FileBuffer = NULL;
					DEBUG ((DEBUG_INFO, " Status = %r\n",Status));
				}

				Firmware_Info->firmware_hash_len = 32;
				Sha256Hash(FileBuffer, Size, Firmware_Info->firmware_hash_content, 32);
				
				DEBUG ((DEBUG_INFO, "SHA256 Hash:\n"));
				for (INTN j = 0; j < 32; j++) {
					DEBUG ((DEBUG_INFO, "%x ",Firmware_Info->firmware_hash_content[j]));
				}
				DEBUG ((DEBUG_INFO, "\n"));
				
				FreePool(Info);
				FreePool(FileBuffer);

				Firmware_Info->firmware_version_len = 1;
				Firmware_Info->firmware_version[0] = 1;

				ResponseSize = sizeof (ResponseData);
				Status = EfiSendCommandToBMC (
									 0x3C,
									 0xF3,
									 (UINT8 *)Firmware_Info,
									 sizeof (FIRMWARE_MEASURE_INFO),
									 ResponseData,
									 &ResponseSize
									 );
				DEBUG ((DEBUG_INFO, "EfiSendCommandToBMC return %r\n", Status));
				DEBUG ((DEBUG_INFO, "ResponseData = %x\n", ResponseData));
			}
		}
		if (DevicePathStr != NULL) {
			FreePool (DevicePathStr);
		}
	}
}

#define ENABLE_POP_UP 0

#if ENABLE_POP_UP
VOID
EFIAPI
CreatePopUp (
  IN  UINTN          Attribute,
  OUT EFI_INPUT_KEY  *Key       OPTIONAL,
  ...
  );
#pragma pack(1)
typedef struct {
  UINT8 firmware_type;  //0:cpu 1:memory 2:NIC 3:gtub/shim
  UINT8 firmware_detail_type;  //default 0
} FIRMWARE_MEASURE_INFO;
#pragma pack()
EFI_STATUS
EfiSendCommandToBMC (
  IN UINT8     NetFunction,
  IN UINT8     Command,
  IN UINT8     *CommandData,
  IN UINT8     CommandDataSize,
  OUT UINT8    *ResponseData,
  OUT UINT8    *ResponseDataSize
  );
#endif  


VOID
EFIAPI
GetVerifyResultFromBMC (
  IN  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption
  )
{
  EFI_STATUS                            Status;
  EFI_HANDLE                            ImageHandle;
  EFI_LOADED_IMAGE_PROTOCOL             *ImageInfo;
  UINT16                                Uint16;
  UINTN                                 OptionNumber;
  UINTN                                 OriginalOptionNumber;
  EFI_DEVICE_PATH_PROTOCOL              *FilePath;
  EFI_DEVICE_PATH_PROTOCOL              *RamDiskDevicePath;
  VOID                                  *FileBuffer;
  UINTN                                 FileSize;

#if ENABLE_POP_UP	
  EFI_INPUT_KEY                         Key;
  CHAR16                                *str; 
  EFI_DEVICE_PATH_PROTOCOL              *TempDp;
  EFI_GUID                              ByoUiAppGuid = {0xD0C9C04A, 0xE796, 0x4c48, {0x9D, 0x52, 0x9E, 0x0C, 0xED, 0x39, 0x4F, 0x4B}};
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *FvFileDp;
  BOOLEAN                               IsByoUi = FALSE;
  FIRMWARE_MEASURE_INFO                 fwinfo;
  UINT8                                 ResponseSize;
  UINT8                                 ResponseData[8];
  UINT32                                i = 0;
  EFI_STATUS                            TepmStatus;
#endif  

  if (BootOption == NULL) {
    return;
  }

  //
  // Set BootCurrent
  //
  Uint16 = (UINT16)OptionNumber;
  BmSetVariableAndReportStatusCodeOnError (
    L"BootCurrent",
    &gEfiGlobalVariableGuid,
    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    sizeof (UINT16),
    &Uint16
    );

  //
  // Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute
  //    the boot option.
  //
  if (IsBootManagerMenu) {
    DEBUG ((DEBUG_INFO, "[Bds] Booting Boot Manager Menu.\n"));
    BmStopHotkeyService (NULL, NULL);
  } else {
    BmRepairAllControllers (0);
  }

  PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32)OptionNumber);

  ImageHandle       = NULL;
  RamDiskDevicePath = NULL;
  if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));

    Status   = EFI_NOT_FOUND;
    FilePath = NULL;
    //
    // Check whether LoadFile is installed for Network Boot Option (PXE or HTTP)
    //
    IsNetworkLoadFileRequried = RequireNetworkLoadFile (BootOption->FilePath);
    EfiBootManagerConnectDevicePath (BootOption->FilePath, NULL);
    if (IsNetworkLoadFileRequried) {
      //
      // If LoadFile is first installed for Network Boot Option (PXE or HTTP), needs to wait 5s for network service ready
      //
      if (RequireNetworkLoadFile (BootOption->FilePath) == FALSE) {
        gBS->Stall (5000000);
      }
    }

#if ENABLE_POP_UP
	str = ConvertDevicePathToText (FilePath, FALSE, FALSE);
    DEBUG ((DEBUG_ERROR,"bmc tpm : LoadFile=%s\n",str));
	if(str != NULL)
	{
		TempDp = FilePath;
	    while(!IsDevicePathEnd(TempDp)){
	        if(DevicePathType(TempDp) == MEDIA_DEVICE_PATH && DevicePathSubType(TempDp) == MEDIA_PIWG_FW_FILE_DP){
	            FvFileDp = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)TempDp;
				DEBUG ((DEBUG_ERROR,"%g %g\n",&FvFileDp->FvFileName,&ByoUiAppGuid));
				DEBUG ((DEBUG_ERROR,"CompareGuid %d\n",CompareGuid(&FvFileDp->FvFileName, &ByoUiAppGuid)));
				if (CompareGuid(&FvFileDp->FvFileName, &ByoUiAppGuid)) {
			        IsByoUi = TRUE;
				}			
				break;
	        }
	        TempDp = NextDevicePathNode(TempDp);
	    }
	}

	if ( IsByoUi == FALSE ) {
		ResponseSize = sizeof(ResponseData);  
	    //
		//  verify bootloader
		//
	    TepmStatus = EFI_NOT_FOUND;
	    for ( i=0;i<3 && TepmStatus != EFI_SUCCESS ;i++ ) {
	        fwinfo.firmware_type = 3;
		    fwinfo.firmware_detail_type = 1;
	        TepmStatus = EfiSendCommandToBMC (
	                      0x3C,
	                      0xF4,
	                     (UINT8 *)&fwinfo,
	                     sizeof (FIRMWARE_MEASURE_INFO),
	                     ResponseData,
	                     &ResponseSize
	                  );
		}
		DEBUG ((DEBUG_ERROR,"os status=%x\n",TepmStatus));
		DEBUG ((DEBUG_ERROR,"ResponseData[0] =%x\n",ResponseData[0] ));
		DEBUG ((DEBUG_ERROR,"ResponseData[1] =%x\n",ResponseData[1] ));
        if ( TepmStatus != EFI_SUCCESS ) {	
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot not respone,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);				
		}
		if ( ResponseData[0] != 1 ) {		
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot verify fail,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);			
		}
	    //
		//  verify pcie
		//
	    TepmStatus = EFI_NOT_FOUND;
	    for ( i=0;i<3 && TepmStatus != EFI_SUCCESS ;i++ )  {
	        fwinfo.firmware_type = 2;
		    fwinfo.firmware_detail_type = 1;
	        TepmStatus = EfiSendCommandToBMC (
	                      0x3C,
	                      0xF4,
	                     (UINT8 *)&fwinfo,
	                     sizeof (FIRMWARE_MEASURE_INFO),
	                     ResponseData,
	                     &ResponseSize
	                  );
		}		
		DEBUG ((DEBUG_ERROR,"pcie status=%x\n",TepmStatus));
		DEBUG ((DEBUG_ERROR,"ResponseData[0] =%x\n",ResponseData[0] ));
		DEBUG ((DEBUG_ERROR,"ResponseData[1] =%x\n",ResponseData[1] ));

        if ( TepmStatus != EFI_SUCCESS ) {			
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot not respone,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);			
		}
		if ( ResponseData[0] != 1 ) {			
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot verify fail,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);			
		}	
	    //
		//  verify memory
		//
	    TepmStatus = EFI_NOT_FOUND;
	    for ( i=0;i<3 && TepmStatus != EFI_SUCCESS ;i++ )  {
	        fwinfo.firmware_type = 1;
		    fwinfo.firmware_detail_type = 0;
	        TepmStatus = EfiSendCommandToBMC (
	                      0x3C,
	                      0xF4,
	                     (UINT8 *)&fwinfo,
	                     sizeof (FIRMWARE_MEASURE_INFO),
	                     ResponseData,
	                     &ResponseSize
	                  );
		}		
		DEBUG ((DEBUG_ERROR,"memory status=%x\n",TepmStatus));
		DEBUG ((DEBUG_ERROR,"ResponseData[0] =%x\n",ResponseData[0] ));
		DEBUG ((DEBUG_ERROR,"ResponseData[1] =%x\n",ResponseData[1] ));

        if ( TepmStatus != EFI_SUCCESS ) {			
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot not respone,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);			
		}
		if ( ResponseData[0] != 1 ) {			
	        CreatePopUp (
	            EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
	            &Key,
	            L"Bmc secure boot verify fail,Press any key to reboot!",
	            NULL
	        );	
			gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);				
		}	
			//
			//	verify CPU
			//
			TepmStatus = EFI_NOT_FOUND;
			for ( i=0;i<3 && TepmStatus != EFI_SUCCESS ;i++ )  {
				fwinfo.firmware_type = 0;
				fwinfo.firmware_detail_type = 0;
				TepmStatus = EfiSendCommandToBMC (
							  0x3C,
							  0xF4,
							 (UINT8 *)&fwinfo,
							 sizeof (FIRMWARE_MEASURE_INFO),
							 ResponseData,
							 &ResponseSize
						  );
			}		
			DEBUG ((DEBUG_ERROR,"cpu status=%x\n",TepmStatus));
			DEBUG ((DEBUG_ERROR,"ResponseData[0] =%x\n",ResponseData[0] ));
			DEBUG ((DEBUG_ERROR,"ResponseData[1] =%x\n",ResponseData[1] ));

			if ( TepmStatus != EFI_SUCCESS ) {			
				CreatePopUp (
					EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
					&Key,
					L"Bmc secure boot not respone,Press any key to reboot!",
					NULL
				);	
				gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);				
			}
			if ( ResponseData[0] != 1 ) {			
				CreatePopUp (
					EFI_LIGHTGRAY | EFI_BACKGROUND_RED,
					&Key,
					L"Bmc secure boot verify fail,Press any key to reboot!",
					NULL
				);	
				gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);			
			}	

	}  
#endif	
    if (FileBuffer != NULL) {
      FreePool (FileBuffer);
    }

    if (FilePath != NULL) {
      FreePool (FilePath);
    }
  }
}
